package online.filter.helper;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.RandomAccess;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

import online.listener.SessionMutexListener;

import core.config.Factory;

/**
 * アクションセションリスト
 *
 * @author Tadsahi Nakayama
 * @version 1.0.0
 */
public final class ActionSessionList
				implements List<String>, HttpSessionBindingListener, RandomAccess, Serializable {
	/** serialVersionUID */
	private static final long serialVersionUID = -5747471454566776036L;

	/** リストクラス */
	private final List<String> list = new ArrayList<>();

	/**
	 * @see javax.servlet.http.HttpSessionBindingListener
	 * #valueBound(javax.servlet.http.HttpSessionBindingEvent)
	 */
	@Override
	public void valueBound(final HttpSessionBindingEvent arg0) {
		HttpSession session = arg0.getSession();

		Map<String, Serializable> m = Factory.cast(
						session.getAttribute(ActionSessionMap.class.getName()));
		if (m != null) {
			synchronized (SessionMutexListener.getMutex(session)) {
				m.clear();
				for (final String key : this.list) {
					m.put(key, Serializable.class.cast(session.getAttribute(key)));
				}
			}
		}
	}

	/**
	 * @see javax.servlet.http.HttpSessionBindingListener
	 * #valueUnbound(javax.servlet.http.HttpSessionBindingEvent)
	 */
	@Override
	public void valueUnbound(final HttpSessionBindingEvent arg0) {
		return;
	}

	/**
	 * @see java.util.List#add(java.lang.Object)
	 */
	@Override
	public boolean add(final String o) {
		return this.list.add(o);
	}

	/**
	 * @see java.util.List#add(int, java.lang.Object)
	 */
	@Override
	public void add(final int index, final String element) {
		this.list.add(index, element);
	}

	/**
	 * @see java.util.List#addAll(java.util.Collection)
	 */
	@Override
	public boolean addAll(final Collection<? extends String> c) {
		return this.list.addAll(c);
	}

	/**
	 * @see java.util.List#addAll(int, java.util.Collection)
	 */
	@Override
	public boolean addAll(final int index, final Collection<? extends String> c) {
		return this.list.addAll(index, c);
	}

	/**
	 * @see java.util.List#clear()
	 */
	@Override
	public void clear() {
		this.list.clear();
	}

	/**
	 * @see java.util.List#contains(java.lang.Object)
	 */
	@Override
	public boolean contains(final Object o) {
		return this.list.contains(o);
	}

	/**
	 * @see java.util.List#containsAll(java.util.Collection)
	 */
	@Override
	public boolean containsAll(final Collection<?> c) {
		return this.list.containsAll(c);
	}

	/**
	 * @see java.util.List#get(int)
	 */
	@Override
	public String get(final int index) {
		return this.list.get(index);
	}

	/**
	 * @see java.util.List#indexOf(java.lang.Object)
	 */
	@Override
	public int indexOf(final Object o) {
		return this.list.indexOf(o);
	}

	/**
	 * @see java.util.List#isEmpty()
	 */
	@Override
	public boolean isEmpty() {
		return this.list.isEmpty();
	}

	/**
	 * @see java.util.List#iterator()
	 */
	@Override
	public Iterator<String> iterator() {
		return this.list.iterator();
	}

	/**
	 * @see java.util.List#lastIndexOf(java.lang.Object)
	 */
	@Override
	public int lastIndexOf(final Object o) {
		return this.list.lastIndexOf(o);
	}

	/**
	 * @see java.util.List#listIterator()
	 */
	@Override
	public ListIterator<String> listIterator() {
		return this.list.listIterator();
	}

	/**
	 * @see java.util.List#listIterator(int)
	 */
	@Override
	public ListIterator<String> listIterator(final int index) {
		return this.list.listIterator(index);
	}

	/**
	 * @see java.util.List#remove(java.lang.Object)
	 */
	@Override
	public boolean remove(final Object o) {
		return this.list.remove(o);
	}

	/**
	 * @see java.util.List#remove(int)
	 */
	@Override
	public String remove(final int index) {
		return this.list.remove(index);
	}

	/**
	 * @see java.util.List#removeAll(java.util.Collection)
	 */
	@Override
	public boolean removeAll(final Collection<?> c) {
		return this.list.removeAll(c);
	}

	/**
	 * @see java.util.List#retainAll(java.util.Collection)
	 */
	@Override
	public boolean retainAll(final Collection<?> c) {
		return this.list.retainAll(c);
	}

	/**
	 * @param index インデックス
	 * @param element エレメント
	 * @return previous element
	 * @see java.util.List#set(int, java.lang.Object)
	 */
	@Override
	public String set(final int index, final String element) {
		return this.list.set(index, element);
	}

	/**
	 * @see java.util.List#size()
	 */
	@Override
	public int size() {
		return this.list.size();
	}

	/**
	 * @see java.util.List#subList(int, int)
	 */
	@Override
	public List<String> subList(final int fromIndex, final int toIndex) {
		return this.list.subList(fromIndex, toIndex);
	}

	/**
	 * @see java.util.List#toArray()
	 */
	@Override
	public Object[] toArray() {
		return this.list.toArray();
	}

	/**
	 * @param a 配列
	 * @param <T> ジェネリックス
	 * @return array
	 */
	@Override
	public <T> T[] toArray(final T[] a) {
		return this.list.toArray(a);
	}
}
